﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Clipper.Model;
using System.Threading;

using Global;
using Communication;
using Clipper.DAL;
using Clipper.Model.EnumModel;
using static Clipper.Model.DataBaseModel.DisplayCup;

namespace Clipper.BLL.DetectChain
{
    /// <summary>
    /// 加试剂2
    /// </summary>
    public class AddReagent2 : ApplianceComponent
    {
        #region // ------成员变量------

        private static Arm mArmR2A = new Arm("R2A", "9");                       // 试剂二臂A
        private static Arm mArmR2B = new Arm("R2B", "10");                      // 试剂二臂B
        private static Arm mArmDish2 = new Arm("TA", "9");                      // 试剂盘2
        private static Arm mArmUsing;                                           // 正在使用的臂

        private static ControlStatusEnum mStatusR2A = ControlStatusEnum.IDLE;           // 试剂二臂A的状态
        private static ControlStatusEnum mStatusR2B = ControlStatusEnum.IDLE;           // 试剂二臂B的状态
        private static ControlStatusEnum mStatusDish2 = ControlStatusEnum.IDLE;         // 试剂盘2的状态
        private static ControlStatusEnum mStatusUsingArm = ControlStatusEnum.IDLE;      // 正在使用的臂状态

        private Clipper.DAL.Reagent mReagent = new DAL.Reagent();               // 试剂信息表
        private Clipper.DAL.ReagentKit mReagentKit = new DAL.ReagentKit();      // 试剂盘信息表
        private Clipper.DAL.DetectItems mDetectItem = new DAL.DetectItems();    // 检测项信息

        #endregion // ------成员变量------

        #region // ------属性------
        /// <summary>
        /// 试剂二臂A
        /// </summary>
        public static Arm ArmR2A
        {
            get { return mArmR2A; }
            set { mArmR2A = value; }
        }

        /// <summary>
        /// 试剂二臂B
        /// </summary>
        public static Arm ArmR2B
        {
            get { return mArmR2B; }
            set { mArmR2B = value; }
        }

        /// <summary>
        /// 试剂盘2
        /// </summary>
        public static Arm ArmDish2
        {
            get { return mArmDish2; }
            set { mArmDish2 = value; }
        }

        #endregion // ------属性------

        #region 变量和属性
        /// <summary>
        /// 执行下一步信号量
        /// </summary>
        static AutoResetEvent mCompleteReset = new AutoResetEvent(false);
        static ControlStatusEnum detectionStatus; 
        int mReagID;
        byte mHoleNum;
        int mStripID;
        /// <summary>
        /// 状态
        /// </summary>
        public override ControlStatusEnum DetectionStatus
        {
            get
            {
                return detectionStatus;
            }
            set
            {
                detectionStatus = value;
            }
        }
        /// <summary>
        /// 当前反应条
        /// </summary>
        public static ReactionStrip CurrentStrip
        {
            get;
            set;
        }
        static AutoResetEvent mPause = new AutoResetEvent(false);//暂停
        static bool mIsPause;
        /// <summary>
        /// 获得或设置模块暂停状态
        /// </summary>
        public static bool IsPause
        {
            get
            {
                return mIsPause;
            }
        }
        /// <summary>
        /// 试剂盘2
        /// </summary>
        public static ReagentKitControl Kit2 = new ReagentKitControl(Can.R2_SUB_ID,Can.R2A_Kit2_ID);
        /// <summary>
        /// 样本2A
        /// </summary>
        public static ArmControl R2A = new ArmControl(Can.R2_SUB_ID,Can.R2A_Kit2_ID, "NC", "AD", "DD", "RC");
        /// <summary>
        /// 样本2B
        /// </summary>
        public static ArmControl R2B = new ArmControl(Can.R2_SUB_ID, Can.R2B_ID,"ND", "AE", "DF", "RD");
        #endregion
   
        #region // 构造函数
        public AddReagent2()
        {
            mArmUsing = mArmR2A;
            PositionCode = 72;
            R2A.Init(18, 8, 11,120,43,45);
            R2B.Init(15, 3, 27,100,43,40);
        }
        #endregion // 构造函数
        public override void Run(ReactionCup cup)
        {



            if (ServiceProvider.Monitor.DisplayCup[cup.StripID * 4 + cup.CupSeatID].getStatus() == CheckCancelEnum.CANCEL)
            {
                //ServiceProvider.Monitor.DisplayCup[cup.CupSeatID].setStatus(CheckCancelEnum.NOTCAN);

                //ServiceProvider.CupStrip[cup.StripID].Cups[cup.CupSeatID].setStatus(Model.DetectionModel.Cup.CupHoleStatusEnum.END);
                //ServiceProvider.Monitor.DisplayCup[cup.StripID * 4 + cup.CupSeatID].CupStatus = "Cancel";
                //int gg = 0;
                //for (int kk = 0; kk < ServiceProvider.CupStrip[cup.StripID].Cups.Count; kk++)
                //{

                //    if (ServiceProvider.CupStrip[cup.StripID].Cups[kk].getStatus() == Model.DetectionModel.Cup.CupHoleStatusEnum.END)
                //        gg++;
                //    if (gg == 4)
                //        ServiceProvider.CupStrip[cup.StripID].setStatus(Model.DetectionModel.CupStrip.ReactionStripStatusEnum.UNLOAD);
                //}
                //return;
            }
            else
            {


                if (ServiceProvider.CupStrip[cup.StripID].Cups[cup.CupSeatID].getStatus() == Model.DetectionModel.Cup.CupHoleStatusEnum.SAMPLE)
                {
                    //添加试剂2指令  此段命令 基本上全执行


                    //cup.StripID  分配的反应条号    加样位置
                    // cup.CupSeatID 分配的反应杯号
                    // cup.DetectItemModel.reagentName2 通过此数据 获取 试剂2 的位置信息

                    //将以上数据 加载到试剂列表中

                    //等待臂完成试剂2加样操作  等待对应 孔位 置状态变化
                    Console.WriteLine("加试剂2操作： 样本号：" + cup.SampleInfoID.ToString() + "\r" +
                                              "条号：" + cup.StripID.ToString() + "\r" +
                                              "杯号：" + cup.CupSeatID.ToString() + "\r" +
                                              "试剂2量：" + cup.DetectItemModel.reagentAmount1.ToString() + "\r"
                                              );

                    ServiceProvider.Monitor.DisplayCup[cup.StripID * 4 + cup.CupSeatID].CupStatus = "添加试剂...";

                    ServiceProvider.ReagentList.Add(cup);

                    while (ServiceProvider.CupStrip[cup.StripID].Cups[cup.CupSeatID].getStatus() != Model.DetectionModel.Cup.CupHoleStatusEnum.REAGENT1)
                    {
                        Thread.Sleep(100);
                    }                    
                }
                else
                {
                    //添加试剂3 指令 此段指令如果量为0 直接执行下一步

                    if (cup.DetectItemModel.reagentAmount3 != 0)
                    {
                        //cup.StripID  分配的反应条号    加样位置
                        // cup.CupSeatID 分配的反应杯号
                        // cup.DetectItemModel.reagentName3 通过此数据 获取 试剂3 的位置信息

                        //将以上数据 加载到试剂列表中

                        //等待臂完成试剂3加样操作  等待对应 孔位 置状态变化
                        Console.WriteLine("加试剂3操作： 样本号：" + cup.SampleInfoID.ToString() + "\r" +
                                             "条号：" + cup.StripID.ToString() + "\r" +
                                             "杯号：" + cup.CupSeatID.ToString() + "\r" +
                                             "试剂3量：" + cup.DetectItemModel.reagentAmount2.ToString() + "\r"
                                             );
                        ServiceProvider.ReagentList.Add(cup);

                        while (ServiceProvider.CupStrip[cup.StripID].Cups[cup.CupSeatID].getStatus() != Model.DetectionModel.Cup.CupHoleStatusEnum.REAGENT2)
                        {
                            Thread.Sleep(100);
                        }
                    }
                    else
                    {
                        ServiceProvider.CupStrip[cup.StripID].Cups[cup.CupSeatID].setStatus(Model.DetectionModel.Cup.CupHoleStatusEnum.REAGENT2);
                    }

                    
                }

               
                //mStripID = strip.ID;
                //CurrentStrip = strip;
                //detectionStatus = ControlStatusEnum.BUSY;
                //strip.ReactionStripSeat = ReactionStripStageEnum.ADDREAGENT2;
                //DetectChainHelper.Position(PositionCode);
                //ServiceProvider.Monitor.R2Position = strip;
                //strip.Note = "add reagent2--" + Thread.CurrentThread.Name + "---" + strip.ID;
                //Console.WriteLine(strip.Note);
                //if (ServiceProvider.IsSimulate)
                //{
                //    Simulate(strip);
                //}
                //else
                //{
                //    for (int i = 0; i < strip.ReactionCupList.Count; i++)
                //    {
                //        if (i < 4)
                //        {
                //            Transportation.TransportB.WaitStatus(Transportation.TransportB.LeftPosition());
                //            AddR2(i, strip.ReactionCupList[i]);
                //        }
                //        else
                //        {
                //            Transportation.TransportB.WaitStatus(Transportation.TransportB.RightPosition());
                //            AddR2(i, strip.ReactionCupList[i]);
                //        }
                //    }
                //}
                //Transportation.AddTransportation(strip, this, NextComponent);
            }
            NextComponent.Run(cup);
        }
        /// <summary>
        /// 加试剂1和加样本
        /// </summary>
        /// <param name="order">使用的试剂臂</param>
        private void AddR2(int order,Model.ReactionCup cup)
        {
            //试剂定位
            if (cup.DetectItem!="")
            {
                mReagID = mReagent.GetReagentID(cup.DetectItem, 2);
                mHoleNum = mReagentKit.GetHoleNumber(mReagID, 2);
                mHoleNum = 1;//调试用
                if (mHoleNum > 0)
                {
                    //Kit2.Position(mHoleNum);
                    ////更新显示数据，更新数据库
                    //ServiceProvider.ReagentKitVM.ReagentKitList[mHoleNum - 1].RemainTimes2--;
                    //Model.Reagent _reagentModel2 = ServiceProvider.ReagentKitVM.ReagentKitList[mHoleNum - 1].ReagentModel2;
                    //_reagentModel2.ReagentLeft -= cup.DetectItemModel.reagentAmount2;
                    //mReagent.Update(_reagentModel2);
                    //Kit2.WaitStatus(1);
                }
                else
                {
                    DetectChainHelper.PostMessage(3005);
                }
            }
            else
            {
                Random random = new Random();
                Kit2.Position(random.Next(1, 12));
                Kit2.WaitStatus(1);
            }

            //if (order % 2 == 0)
            if (true)
            {
                //if (order != 0)
                //{
                    //R2A.WaitStatus(3);
                    //R2A.RinseInEnd(true);
                //}
                while (R2A.ControlStatus != ControlStatusEnum.IDLE)
                {
                    //Console.WriteLine("cccc");
                }
                R2A.ControlStatus = ControlStatusEnum.BUSY;
                //试剂2A
                R2A.Imbibe();
                R2A.WaitStatus(1);
                
                R2A.Inject();
                R2A.WaitStatus(2);
                Kit2.Reset();
                R2A.Rinse();
                R2A.WaitRinseTime();
                Kit2.WaitStatus(0);
            }
            else
            {
                //if (order != 1)
                //{
                    //R2B.WaitStatus(3);
                    //R2B.RinseInEnd(true);
                //}
                //while (R2B.ControlStatus != ControlStatusEnum.IDLE)
                //{
                //    //Console.WriteLine("ddddd");
                //}
                R2B.ControlStatus = ControlStatusEnum.BUSY;

                //试剂2B
                R2B.Imbibe();
                R2B.WaitStatus(1);
                R2B.Inject();
                R2B.WaitStatus(2);
                Kit2.Reset();
                R2B.Rinse();
                R2B.WaitRinseTime();
                Kit2.WaitStatus(0);
            }
        }

        /// <summary>
        /// 演示方法
        /// </summary>
        /// <param name="strip"></param>
        public override void Simulate(Model.ReactionCup strip)
        {
            if (IsPause)//局部暂停
            {
                mPause.WaitOne();
            }
            do
            {
                Thread.Sleep(ServiceProvider.Reagent2SleepTime);
            } while (ServiceProvider.Monitor.ReagentPlate1State == ComponentStateEnum.ERROR);
        }
        /// <summary>
        /// 工程师调试方法
        /// </summary>
        /// <param name="strip">反应条</param>
        public static void RunEngineer(ReactionStrip strip)
        {
            AddReagent2 addR2 = new AddReagent2();
            for (int i = 0; i < 4; i++)
            {
                Transportation.TransportB.LeftPosition();
                Transportation.TransportB.WaitStatus(1);

                if (i % 2 == 0)
                {
                    addR2.AddR2(1,strip.ReactionCupList[i]);
                }
                else
                {
                    addR2.AddR2(2,strip.ReactionCupList[i]);
                }
            }

            for (int i = 0; i < 4; i++)
            {
                Transportation.TransportB.RightPosition();
                Transportation.TransportB.WaitStatus(2);
                if (i % 2 == 0)
                {
                    addR2.AddR2(1,strip.ReactionCupList[i]);
                }
                else
                {
                    addR2.AddR2(2,strip.ReactionCupList[i]);
                }
            }
        }
        /// <summary>
        /// 复位
        /// </summary>
        /// <returns></returns>
        public static bool Reset()
        {
            R2A.Reset();
            R2B.Reset();
            R2A.WaitStatus(0);
            R2B.WaitStatus(0);

            Kit2.Reset();
            Transportation.TransportB.Home();

            Kit2.WaitStatus(0);
            Transportation.TransportB.WaitStatus(0);
            return true;
        }
    
        /// <summary>
        /// 暂停/恢复
        /// </summary>
        /// <param name="isPause">暂停true,恢复false</param>
        public static void Pause(bool isPause)
        {
            mIsPause = isPause;
            R2A.IsPause = isPause;
            R2B.IsPause = isPause;
            Kit2.IsPause = isPause;
        }
        #region // 模块运行控制，Anry
        private void RunControl(ReactionStrip strip)
        {
            string sendCmd = "";    // 发送命令
            int reagID = 0;         // 试剂编号
            byte holeNum = 0;       // 孔位编号
            Clipper.Model.ReagentKit reagKit = new Model.ReagentKit();      // 试剂盘对象
            Clipper.Model.DetectItems detItem = new Model.DetectItems();    // 检测项对象   

            for (byte i = 0; i < strip.ReactionCupList.Count(); i++)
            {
                #region // 将试剂盘2转到相应位置
                // 如果模块需要暂停，则暂停模块运行，等待外部改变此状态且继续模块运行
                if (IsPause)
                {
                    mPause.WaitOne();
                }

                // 如果试剂盘2空闲，将试剂盘2转到指定位置，将试剂盘状态设置为忙
                if (mStatusDish2 == ControlStatusEnum.IDLE)
                {
                    // 查找试剂所在试剂盘的孔位
                    reagID = mReagent.GetReagentID(strip.ReactionCupList[i].DetectItem, 2);
                    holeNum = mReagentKit.GetHoleNumber(reagID, 2);
                    sendCmd = mArmR2A.LocateReagentDish(holeNum);
                    Can.SendDataToCan(Convert.ToInt16(mArmR2A.CanID), sendCmd);
                    mStatusDish2 = ControlStatusEnum.BUSY;
                }
                else
                {
                    // 处理异常，程序退出
                }

                #endregion // 将试剂盘2转到相应位置

                #region // 反应杯进给：滑轨B将反应条的第一个杯传送到加试剂2的位置
                if (IsPause)
                {
                    mPause.WaitOne();
                }

                // 如果滑轨B空闲,则它将反应条下一个杯移到加试剂2位置
                if (ServiceProvider.gStatusSlideB == ControlStatusEnum.IDLE)
                {
                    Transportation.AssayCupFeeding('B', (byte)(i + 1));
                    ServiceProvider.gStatusSlideB = ControlStatusEnum.BUSY;
                }

                // 等待滑轨B到位
                while (ServiceProvider.gStatusSlideB == ControlStatusEnum.BUSY)
                {
                    System.Threading.Thread.Sleep(ServiceProvider.gInteralmSec);
                }

                // 等待试剂盘2到位
                while (mStatusDish2 == ControlStatusEnum.BUSY)
                {
                    System.Threading.Thread.Sleep(ServiceProvider.gInteralmSec);
                }
                #endregion // 反应杯进给：滑轨B将反应条的第一个杯传送到加试剂2的位置

                #region // 吸试剂2：R2A或R2B吸试剂2
                // 如果R2A空闲，则使用臂R2A
                if (mStatusR2A == ControlStatusEnum.IDLE)
                {
                    mArmUsing = mArmR2A;
                }
                // 如果R2B空闲，则使用臂R2B
                else if (mStatusR2B == ControlStatusEnum.IDLE)
                {
                    mArmUsing = mArmR2B;
                }
                else
                {
                    // 处理异常，程序退出
                }

                // 如果模块需要暂停，则暂停模块运行，等待外部改变此状态且继续模块运行
                if (IsPause)
                {
                    mPause.WaitOne();
                }

                reagKit = mReagentKit.GetModel(holeNum);                                // 获得试剂盘对象
                detItem = mDetectItem.GetModel(strip.ReactionCupList[i].DetectItem);    // 获得检查项对象

                // 如果试剂盘2转到位，且滑轨B空闲
                if (mStatusDish2 == ControlStatusEnum.IDLE && ServiceProvider.gStatusSlideB == ControlStatusEnum.IDLE)
                {
                    //// 如果剩余试剂量够用，则吸试剂，将当前臂的状态设置为忙
                    //if (reagKit.ReagentModel2.ReagentLeft > detItem.reagentAmount2)
                    //{
                    //    sendCmd = mArmUsing.Aspirate(detItem.reagentAmount2);           // 生成吸试剂命令
                    //    Can.SendDataToCan(Convert.ToInt16(mArmUsing.CanID), sendCmd);   // 发送吸试剂命令
                    //    reagKit.ReagentModel2.ReagentLeft -= detItem.reagentAmount2;                 // 记录当前试剂量
                    //    mReagentKit.Update(reagKit);                                    // 更新数据库内容
                    //    mStatusUsingArm = ControlStatusEnum.BUSY;                       // 设置臂状态为忙
                    //}
                    //else
                    //{
                    //    // 弹出界面，提醒用户更换试剂
                    //    // 暂停本模块的运行
                    //    // 更换完成之后，再转到试剂剩余量的判断
                    //}
                }

                // 等待吸试剂完成
                while (mStatusUsingArm == ControlStatusEnum.BUSY)
                {
                    System.Threading.Thread.Sleep(ServiceProvider.gInteralmSec);
                }
                #endregion // 吸试剂2：R2A或R2B吸试剂2

                #region // 加试剂2：R2A或R2B加试剂2
                // 如果模块需要暂停，则暂停模块运行，等待外部改变此状态且继续模块运行
                if (IsPause)
                {
                    mPause.WaitOne();
                }

                // 如果R2B吸试剂2完成，且反应杯到位，则加试剂,将当前臂的状态设置为忙
                if (mStatusUsingArm == ControlStatusEnum.IDLE && ServiceProvider.gStatusSlideB == ControlStatusEnum.IDLE)
                {
                    sendCmd = mArmUsing.Dispense();
                    Can.SendDataToCan(Convert.ToInt16(mArmUsing.CanID), sendCmd);
                    mStatusUsingArm = ControlStatusEnum.BUSY;
                }

                // 等待加试剂完成
                while (mStatusUsingArm == ControlStatusEnum.BUSY)
                {
                    System.Threading.Thread.Sleep(ServiceProvider.gInteralmSec);
                }
                #endregion // 加试剂2：R2A或R2B加试剂2

                #region // 洗针：清洗加完试剂的针
                // 如果模块需要暂停，则暂停模块运行，等待外部改变此状态且继续模块运行
                if (IsPause)
                {
                    mPause.WaitOne();
                }

                // 条件：加试剂2完成,且清洗液的量够用

                if (mStatusUsingArm == ControlStatusEnum.IDLE)
                {
                    sendCmd = mArmUsing.RinseNeedle();
                    Can.SendDataToCan(Convert.ToInt16(mArmUsing.CanID), sendCmd);
                    mStatusUsingArm = ControlStatusEnum.BUSY;
                }
                #endregion // 洗针：清洗加完试剂的针
            }
        }

        #endregion // 模块运行控制，Anry
    }
}
